home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / program / huge.zip / HUGEARR.C < prev    next >
C/C++ Source or Header  |  1991-06-26  |  16KB  |  376 lines

  1. /************************************************************************
  2. *                                                                       *
  3. *                               HUGEARR.DLL                             *
  4. *                                                                       *
  5. *               Huge array support for Microsoft Visual Basic           *
  6. *                                                                       *
  7. *                             By Mike Warning                           *
  8. *                                                                       *
  9. ************************************************************************/
  10.  
  11. #include <memory.h>
  12. #include <windows.h>
  13. #include "hugearr.h"
  14.  
  15. HANDLE                  hLocalMem;              // handle to local memory
  16. int                     NumArrays;              // total number of arrays
  17.  
  18. /************************************************************************
  19. * LibMain -                                                             *
  20. *   Standard DLL constructor.  Allocates all of local heap to store     *
  21. * array descriptors and then set the total number of arrays possible.   *
  22. ************************************************************************/
  23. int FAR pascal
  24.      LibMain(HANDLE hModule, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine)
  25. {
  26.     if (cbHeapSize > 0)
  27.         UnlockData(0);
  28.                                         // Allocate memory for array descrips.
  29.     hLocalMem = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT,
  30.                                              LocalCompact((WORD) 65500));
  31.     if (hLocalMem == NULL)
  32.         return 0;                       // Something happened, bomb out
  33.                                         // calc total number of arrays
  34.     NumArrays = (int) (LocalSize(hLocalMem) / sizeof(struct ArrayDesc));
  35.     return (1);
  36. }
  37.  
  38. /************************************************************************
  39. * WEP -                                                                 *
  40. *   Standard DLL destructor.  Free up local memory and quit.            *
  41. ************************************************************************/
  42. int FAR pascal WEP(int bSystemExit)
  43. {
  44.     LocalFree(hLocalMem);
  45.     return (1);
  46. }
  47.  
  48. /************************************************************************
  49. * HugeDim -                                                             *
  50. *   Dimensions a new array.  The size of the array is                   *
  51. * (recsize * ubound+1). Recsize is the size in bytes of each element in *
  52. * the array and ubound is the upper bound of the array. All arrays have *
  53. * a lower bound of 0.                                                   *
  54. *                                                                       *
  55. * Note: If total size of the array is greater than 64k, recsize should  *
  56. *       be an integer power of two (1,2,4,8,16,etc.)  Otherwise, the    *
  57. *       huge pointers will not be added correctly.                      *
  58. ************************************************************************/
  59. int FAR pascal HugeDim(int recsize, long ubound)
  60. {
  61.     int         hArray;                 // handle to array to dimension
  62.     pDescrip    pArray;                 // pointer to array descriptor
  63.     int         ret;                    // return value from HugeAlloc
  64.  
  65.     pArray = (pDescrip) LocalLock(hLocalMem);   // find a free array
  66.     if ((hArray = GetFreeArray(pArray)) == HA_TOMANYARRAYS)  {
  67.         LocalUnlock(hLocalMem);                 // couldn't find one,
  68.         return (HA_TOMANYARRAYS);               // return error.
  69.     }
  70.                                         // allocate new array
  71.     ret = HugeAlloc(pArray + hArray, recsize, ubound, FALSE);
  72.     LocalUnlock(hLocalMem);
  73.  
  74.     if (ret < 0)                        // if an error occured during alloc
  75.         return (ret);                   // return the error, else
  76.     else
  77.         return (hArray);                // return the handle to the array
  78.  
  79. }
  80.  
  81. /************************************************************************
  82. * HugeRedim -                                                           *
  83. *   Redimenions the given array to have the new 'ubound'.  The old      *
  84. * recsize is kept.  All data in the array is preserved and any new data *
  85. * (created by expanding the array) is initialized to 0.                 *
  86. *                                                                       *
  87. * Note: The recsize must be an integer power of two if the total array  *
  88. *       size is greater than 64k.                                       *
  89. ************************************************************************/
  90. int FAR pascal HugeRedim(int hArray, long ubound)
  91. {
  92.     pDescrip    pArray;                 // pointer to array desciptor
  93.     register    ret;                    // return code of HugeAlloc
  94.  
  95.     if (hArray < 0 | hArray >= NumArrays)
  96.         return (HA_BADARRAY);           // illegal array handle
  97.  
  98.     pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
  99.  
  100.     if (pArray -> handle != NULL)       // reallocate array
  101.         ret = HugeAlloc(pArray, pArray -> recsize, ubound, TRUE);
  102.     else
  103.         ret = HA_BADARRAY;              // array has never been allocated
  104.  
  105.     LocalUnlock(hLocalMem);
  106.     return (ret);
  107. }
  108.  
  109.  
  110. /********************************************************************
  111. * GetFreeArray -                                                    *
  112. *   Searches the array descriptor table looking for a free entry.   *
  113. * It returns the index into the table if an entry is free or        *
  114. * HA_TOMANYARRAYS otherwise.  pArray is the pointer to the start of *
  115. * the table.                                                        *
  116. ********************************************************************/
  117. int GetFreeArray(pDescrip pArray)
  118. {
  119.     int i = 0;
  120.                                         // loop until found or out of entries
  121.     while ((i < NumArrays) && (pArray -> handle != NULL))  {
  122.         ++pArray;
  123.         ++i;
  124.     }
  125.  
  126.     if (i == NumArrays)                 // didn't find a spot
  127.         return (HA_TOMANYARRAYS);
  128.  
  129.     return (i);                         // found one, return index to it
  130. }
  131.  
  132. /********************************************************************
  133. * GetHugeEl -                                                       *
  134. *   Retrieves an element of the array storing it into the buffer    *
  135. * pointed to by 'buffer'.  hArray is the index into the descriptor  *
  136. * table of the array, element is the element to get.                *
  137. *                                                                   *
  138. * NOTE: there is absolutely no type checking done on the buffer.    *
  139. *       It is up to the programmer to make sure it points to the    *
  140. *       correct data type.                                          *
  141. ********************************************************************/
  142. int FAR pascal GetHugeEl(int hArray, long element, BYTE FAR *buffer)
  143. {
  144.     BYTE _huge          *ptr;               // pointer to array element
  145.     pDescrip            pArray;             // pointer to array descriptor
  146.  
  147.     if (hArray < 0 || hArray >= NumArrays)
  148.         return (HA_BADARRAY);               // illegal array handle
  149.  
  150.                                             // point to proper descriptor
  151.     pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
  152.  
  153.     if (pArray -> handle == NULL)  {
  154.         LocalUnlock(hLocalMem);
  155.         return (HA_BADARRAY);               // array hasn't been allocated
  156.     }
  157.     if ((pArray -> ubound < element) || (element < 0))  {
  158.         LocalUnlock(hLocalMem);
  159.         return (HA_SUBSCRIPT);              // subscript out of range
  160.     }
  161.                                             // calculate pointer to element
  162.     ptr = (BYTE _huge *) GlobalLock(pArray -> handle);
  163.     ptr = ptr + element * pArray->recsize;
  164.     _fmemcpy(buffer, ptr, pArray -> recsize);   // copy data
  165.  
  166.     GlobalUnlock(pArray -> handle);
  167.     LocalUnlock(hLocalMem);
  168.     return (HA_OK);
  169. }
  170.  
  171. /********************************************************************
  172. * SetHugeEl -                                                       *
  173. *   Sets the value of an array element.  This routine is exactly    *
  174. * the same as 'GetHugeEl' except that the memory copy is resversed. *
  175. ********************************************************************/
  176. int FAR pascal SetHugeEl(int hArray, long element, BYTE FAR *buffer)
  177. {
  178.     BYTE _huge          *ptr;               // pointer to array element
  179.     pDescrip            pArray;             // pointer to array descriptor
  180.  
  181.     if (hArray < 0 || hArray >= NumArrays)
  182.         return (HA_BADARRAY);               // illegal array handle
  183.  
  184.                                             // point to proper descriptor
  185.     pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
  186.  
  187.     if (pArray -> handle == NULL)  {
  188.         LocalUnlock(hLocalMem);
  189.         return (HA_BADARRAY);               // array hasn't been allocated
  190.     }
  191.     if ((pArray -> ubound < element) || (element < 0))  {
  192.         LocalUnlock(hLocalMem);
  193.         return (HA_SUBSCRIPT);              // subscript out of range
  194.     }
  195.                                             // calculate pointer to element
  196.     ptr = (BYTE _huge *) GlobalLock(pArray -> handle);
  197.     ptr = ptr + element * pArray->recsize;
  198.     _fmemcpy(ptr, buffer, pArray -> recsize);   // copy data
  199.  
  200.     GlobalUnlock(pArray -> handle);
  201.     LocalUnlock(hLocalMem);
  202.     return (HA_OK);
  203. }
  204.  
  205. /********************************************************************
  206. * HugeErase -                                                       *
  207. *   Deletes an array and marks it as free in the descriptor table.  *
  208. * 'hArray' is the array to erase.                                   *
  209. ********************************************************************/
  210. int FAR pascal HugeErase(int hArray)
  211. {
  212.     pDescrip    pArray;                     // pointer to array descriptor
  213.  
  214.     if (hArray < 0 || hArray >= NumArrays)
  215.         return (HA_BADARRAY);               // illegal array handle
  216.  
  217.     pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
  218.     if (pArray -> handle == NULL)  {
  219.         LocalUnlock(hLocalMem);
  220.         return (HA_BADARRAY);               // array hasn't been allocated yet
  221.     }
  222.  
  223.     GlobalFree(pArray -> handle);           // free the memory
  224.     pArray -> handle = NULL;
  225.  
  226.     LocalUnlock(hLocalMem);
  227.     return (HA_OK);
  228. }
  229.  
  230. /********************************************************************
  231. * NumHugeArrays -                                                   *
  232. *   Returns the number of free entries in the array descriptor table*
  233. ********************************************************************/
  234. int FAR pascal NumHugeArrays(void)
  235. {
  236.     pDescrip            pArray;             // pointer to current descriptor
  237.     int                 num, i;             // number free so far
  238.  
  239.     pArray = (pDescrip) LocalLock(hLocalMem);
  240.     for (i = 0, num = 0; i < NumArrays; i++, pArray++)
  241.         if (pArray -> handle == NULL)
  242.             ++num;
  243.  
  244.     LocalUnlock(hLocalMem);
  245.     return (num);
  246. }
  247.  
  248.  
  249. /********************************************************************
  250. * HugeUbound -                                                      *
  251. *   Returns the upper bound of a given array                        *
  252. ********************************************************************/
  253. long FAR pascal HugeUbound(int hArray)
  254. {
  255.     pDescrip    pArray;                     // pointer to array descriptor
  256.     long    ubound;                     // upper bound of array
  257.  
  258.     if (hArray < 0 || hArray >= NumArrays)
  259.         return (HA_BADARRAY);               // illegal array handle
  260.  
  261.     pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
  262.     if (pArray -> handle == NULL)  {
  263.         LocalUnlock(hLocalMem);
  264.         return (HA_BADARRAY);               // array hasn't been allocated yet
  265.     }
  266.  
  267.     ubound = pArray -> ubound;
  268.     LocalUnlock(hLocalMem);
  269.  
  270.     return (ubound);
  271. }
  272.  
  273.  
  274. /********************************************************************
  275. * HugeInt -                                                         *
  276. *   Same as GetHugeEl except that it explicitly returns an integer. *
  277. * Use this function when you are in an expression such as:          *
  278. *           i% = 5 * HugeInt(4, 5)                                  *
  279. *                                                                   *
  280. * NOTE: Because the user could store anything in the array element, *
  281. *       they will not know if the value returned is a real value or *
  282. *       if an error occured.  Use GetHugeEl if the error code must  *
  283. *       be checked.                                                 *
  284. ********************************************************************/
  285. int FAR pascal HugeInt(int hArray, long element)
  286. {
  287.     int     retval;
  288.  
  289.     GetHugeEl(hArray, element, (BYTE FAR *) &retval);
  290.     return (retval);
  291. }
  292.  
  293.  
  294. /********************************************************************
  295. * HugeLong -                                                        *
  296. *   Returns an element of a long integer array.  (re. HugeInt)      *
  297. ********************************************************************/
  298. long FAR pascal HugeLong(int hArray, long element)
  299. {
  300.     long    retval;
  301.  
  302.     GetHugeEl(hArray, element, (BYTE FAR *) &retval);
  303.     return (retval);
  304. }
  305.  
  306.  
  307.  
  308. /********************************************************************
  309. * HugeSingle -                                                      *
  310. *   Returns an element of a single precesion array.  (re. HugeInt)  *
  311. ********************************************************************/
  312. float FAR pascal HugeSingle(int hArray, long element)
  313. {
  314.     float  retval;
  315.  
  316.     GetHugeEl(hArray, element, (BYTE FAR *) &retval);
  317.     return (retval);
  318. }
  319.  
  320.  
  321. /********************************************************************
  322. * HugeDouble -                                                      *
  323. *   Returns an element of a double precesion array.  (re. HugeInt)  *
  324. ********************************************************************/
  325. double FAR pascal HugeDouble(int hArray, long element)
  326. {
  327.     double  retval;
  328.  
  329.     GetHugeEl(hArray, element, (BYTE FAR *) &retval);
  330.     return (retval);
  331. }
  332.  
  333.  
  334. /********************************************************************
  335. * HugeCurrency -                                                    *
  336. *   Returns an element of a currency array.  (re. HugeInt)          *
  337. ********************************************************************/
  338. currency FAR pascal HugeCurrency(int hArray, long element)
  339. {
  340.     return((currency) HugeDouble(hArray, element));
  341. }
  342.  
  343. /********************************************************************
  344. *   HugeAlloc -                                                     *
  345. * Allocates (or reallocates) global memory for an array.  The size  *
  346. * of the array is recsize * (ubound + 1) bytes.  The information    *
  347. * for the array is stored in the array descriptor pointed to by     *
  348. * 'pArray'.                                                         *
  349. *                                                                   *
  350. * Note:  See HugeDim for a discussion on array size limitations.    *
  351. ********************************************************************/
  352. int HugeAlloc(pDescrip pArray,int recsize,long ubound, BOOL realloc)
  353. {
  354.     HANDLE              handle;             // temp handle for alloc
  355.  
  356.     ++ubound;                               // ubound = #elements - 1
  357.     if (recsize * ubound > 0xffff)          // is size integer power two?
  358.         if ((recsize <= 0) || (((recsize - 1) & recsize) != 0))
  359.             return (HA_BADELEMENTSIZE);
  360.  
  361.     if (realloc)                            // allocate array
  362.         handle = GlobalReAlloc(pArray -> handle, recsize * ubound,
  363.                                                GMEM_MOVEABLE || GMEM_ZEROINIT);
  364.     else
  365.         handle = GlobalAlloc(GMEM_MOVEABLE || GMEM_ZEROINIT, recsize * ubound);
  366.  
  367.     if (handle == NULL)
  368.         return (HA_OUTOFMEMORY);            // out of memory
  369.  
  370.     pArray -> handle = handle;              // save new handle
  371.     pArray -> recsize = recsize;            // record element size
  372.     pArray -> ubound = ubound - 1;
  373.  
  374.     return (HA_OK);
  375. }
  376.